package main

import (
	"context"
	"demo/grpc/proto"
	"fmt"
	"io"
	"log"
	"time"

	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"

	"google.golang.org/grpc"
)

var client proto.UserServerClient
var articleClient proto.ArticleServerClient
var ctx context.Context
var cancel context.CancelFunc

func main() {
	//读取证书和服务名
	/*crt, err := credentials.NewClientTLSFromFile("./test.pem", "www.zchd.ltd")
	if err != nil {
		panic(err.Error())
	}*/
	connect, err := grpc.Dial("127.0.0.1:9527", grpc.WithInsecure())
	//connect, err := grpc.Dial("127.0.0.1:9527", grpc.WithTransportCredentials(crt))
	if err != nil {
		log.Fatalln(err)
	}

	defer connect.Close()

	ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
	defer cancel()

	client = proto.NewUserServerClient(connect)
	articleClient = proto.NewArticleServerClient(connect)

	SaveUser()
	//GetUserInfo()
	//
	//SaveArticle()
	//GetArticleInfo()
	//DeleteArticle()
}

func SaveUser() {
	params := proto.UserParams{}
	params.Age = &proto.Age{Age: 31}
	params.Name = &proto.Name{Name: "test"}

	//打印当前时间
	fmt.Println(time.Now().Format("2006-01-02 15:04:05"))

	res, err := client.SaveUser(ctx, &params)
	if err != nil {
		got := status.Code(err)
		if got == codes.DeadlineExceeded {
			log.Println("client.SaveUser err: deadline")
		}
		log.Fatalf("client.SaveUser err: %v", err)
	} else {
		fmt.Printf("%+v\n", res.Id)
	}
}

func GetUserInfo() {
	res, err := client.GetUserInfo(context.Background(), &proto.Id{Id: 1})
	if err != nil {
		log.Fatalf("client.userInfo err:%v", err)
	}
	fmt.Printf("%+v\n", res)
}

func SaveArticle() {
	// 定义数据
	saveList := map[string]proto.ArticleParam{
		"1": {Author: &proto.Author{Author: "tony"}, Title: &proto.Title{Title: "title1"}, Content: &proto.Content{Content: "content1"}},
		"2": {Author: &proto.Author{Author: "jack"}, Title: &proto.Title{Title: "title2"}, Content: &proto.Content{Content: "content2"}},
		"3": {Author: &proto.Author{Author: "tom"}, Title: &proto.Title{Title: "title3"}, Content: &proto.Content{Content: "content3"}},
		"4": {Author: &proto.Author{Author: "bob"}, Title: &proto.Title{Title: "title4"}, Content: &proto.Content{Content: "content4"}},
	}
	// 调用方法
	stream, err := articleClient.SaveArticle(context.Background())

	if err != nil {
		log.Fatal("saveArticle grpc fail", err.Error())
	}
	// 循环发送
	for _, info := range saveList {
		err = stream.Send(&info)
		if err != nil {
			log.Fatal("saveArticle Send info fail", err.Error())
		}
	}
	// 发送关闭新号，并且获取返回值
	resp, err := stream.CloseAndRecv()
	if err != nil {
		log.Fatal("saveArticle CloseAndRecv fail", err.Error())
	}

	fmt.Printf("resp: id = %d", resp.GetId())
}

func SaveArticle2() {

	//定义一组数据
	SaveInfo := proto.ArticleParam{
		Author: &proto.Author{Author: "mark"}, Title: &proto.Title{Title: "title5"}, Content: &proto.Content{Content: "content5"},
	}

	//先调用函数
	stream, err := articleClient.SaveArticle(context.Background())

	if err != nil {
		log.Fatal("SaveArticle grpc fail", err.Error())
	}

	//发送
	err = stream.Send(&SaveInfo)
	if err != nil {
		log.Fatal("SaveArticle Send info fail", err.Error())
	}

	////发送关闭新号，并且获取返回值
	resp, err := stream.CloseAndRecv()
	if err != nil {
		log.Fatal("SaveArticle CloseAndRecv fail", err.Error())
	}

	fmt.Printf("resp: id = %d", resp.GetId())
}

func GetArticleInfo() {
	aid := &proto.Aid{
		Id: 2,
	}
	// 请求
	stream, err := articleClient.GetArticleInfo(context.Background(), aid)
	if err != nil {
		log.Fatal("GetArticleInfo grpc fail", err.Error())
	}
	// 循环接收数据
	for {
		r, err := stream.Recv()
		if err == io.EOF {
			fmt.Println("读取数据结束")
			break
		}
		if err != nil {
			log.Fatal("GetArticleInfo Recv fail", err.Error())
		}

		fmt.Printf("stream.rev aid:%d, author:%s, title:%s, context: %s\n", r.GetId(), r.GetAuthor(), r.GetTitle(), r.GetContent())
	}
}

// 双向流
func DeleteArticle() {
	stream, err := articleClient.DeleteArticle(context.Background())
	if err != nil {
		log.Fatal("DeleteArticle grpc fail", err.Error())
	}

	for i := 0; i < 6; i++ {
		// 先发送
		err = stream.Send(&proto.Aid{Id: int32(i)})
		if err != nil {
			log.Fatal("DeleteArticle Send fail", err.Error())
		}

		// 再接收
		r, err := stream.Recv()
		if err == io.EOF {
			break
		}

		if err != nil {
			log.Fatal("GetArticleInfo Recv fail", err.Error())
		}

		fmt.Printf("stream.rev status:%v\n", r.GetCode())
	}

	// 发送结束
	_ = stream.CloseSend()
}
